package com.docker.manege.container;

import com.alibaba.fastjson.JSONObject;
import com.docker.comment.ShellUtil;
import com.docker.core.mvc.service.BaseService;
import com.docker.core.third.docker.DockerKit;
import com.docker.core.third.docker.SelfDockerClient;
import com.docker.core.third.websocket.WebsocketCMD;
import com.docker.core.third.websocket.WebsocketPool;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.model.Container;
import com.github.dockerjava.api.model.ContainerNetwork;
import com.github.dockerjava.api.model.ContainerNetworkSettings;
import com.github.dockerjava.api.model.ContainerPort;
import com.jfinal.aop.Inject;
import com.jfinal.kit.Okv;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Record;
import kit.docker.convert.RecordKit;

import javax.websocket.Session;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author wangbei
 * @date 2020/12/4 - 10:39
 */
public class ContainerService extends BaseService {

    @Inject
    private ContainerDao containerDao;

    public List<Record> list(String clientKey, String containerId, String containerName) {
        List<Record> result = new ArrayList<>();

        List<Container> containers = DockerKit.containers(clientKey, containerId, containerName);
        Record cont;
        for (Container container : containers) {
            cont = new Record();

            //获取容器端口号
            String portStr = "";
            ContainerPort[] ports = container.getPorts();
            for (ContainerPort port : ports) {
                if (StrKit.notNull(port.getIp(), port.getType(), port.getPrivatePort(), port.getPublicPort())) {
                    portStr = portStr + port.getPublicPort() + ":" + port.getPrivatePort() + "  ";
                }
            }
            //获取容器名称
            String[] containerNameArr = container.getNames();
            String containerNameStr = containerNameArr[0].substring(1);
            cont.set("container_id", container.getId());
            cont.set("container_name", containerNameStr);
            cont.set("container_state", container.getState());
            cont.set("container_status", container.getStatus());
//            cont.set("create_time", DateKit.timestampFormat(container.getCreated(), DateStyle.YYYY_MM_DD_HH_MM_SS));
            cont.set("container_ports", portStr);
            cont.set("image_name", container.getImage());
            cont.set("image_id", container.getImageId());
            cont.set("command", container.getCommand());
            cont.set("labels", container.getLabels());
            cont.set("mounts", container.getMounts());
            cont.set("network_settings", container.getNetworkSettings());
            cont.set("size_rootfs", container.getSizeRootFs());
            cont.set("size_rw", container.getSizeRw());
            cont.set("ip_address", getIPAddress(container.getNetworkSettings()));
            result.add(cont);
        }
        return result;
    }

    private Record getIPAddress(ContainerNetworkSettings networkSettings) {
        Record ip = new Record();
        if (!StrKit.notNull(networkSettings)) {
            return ip;
        }
        Map<String, ContainerNetwork> networks = networkSettings.getNetworks();
        for (ContainerNetwork network : networks.values()) {
            if (StrKit.notNull(network)) {
                ip.set("gate_way", network.getGateway());
                ip.set("ip_address", network.getIpAddress());
            }
        }
        return ip;
    }

    public boolean start(String clientKey, String containerId) {
        SelfDockerClient dockerClient = getDockerClient(clientKey);
        List<Container> containers = DockerKit.containers(dockerClient, containerId, null);
        if (!StrKit.notNull(containers) || containers.size() == 0) {
            throwError("容器不存在");
        }
        //获取当前容器信息
        Container container = containers.get(0);
        if (!StrKit.notNull(container)) {
            throwError("容器不存在");
        }
        //如果容器处于运行状态,直接返回true
        if ("running".equals(container.getState())) {
            throwError("容器已启动");
        }
        if (!DockerKit.startContainer(dockerClient, containerId)) {
            throwError("容器启动失败");
        }
        return true;
    }

    public boolean stop(String clientKey, String containerId) {
        //获取当前容器信息
        Container container = DockerKit.containers(clientKey, containerId, null).get(0);
        if (!StrKit.notNull(container)) {
            throwError("容器不存在");
        }
        //如果容器处于停止状态,直接返回true
        if ("exited".equals(container.getState())) {
            return true;
        }
        if (!DockerKit.stopContainer(clientKey, containerId)) {
            throwError("容器停止失败");
        }
        return true;
    }

    public boolean reStart(String clientKey, String containerId) {
        if (!DockerKit.restartContainer(clientKey, containerId)) {
            throwError("容器重新启动失败");
        }
        return true;
    }

    public boolean save(ContainerBean bean, String clientKey, String userId) {
        if (containerDao.exist(bean.getServer_id(), bean.getContainer_name(), "-1")) {
            throwError("容器已存在");
        }
        bean.setCr_id(getUUID32());
        bean.setStatus_flag("1");
        bean.setRemark("新建容器");
        bean.setCreate_time(getNowDateTime());
        bean.setCreate_oper_id(userId);
        bean.setUpdate_time(bean.getCreate_time());
        bean.setUpdate_oper_id(bean.getCreate_oper_id());
        return tx(() -> {
            if (!containerDao.save(RecordKit.objectToRecord(bean))) {
                throwError("容器创建失败");
            }
            CreateContainerResponse containerResponse = DockerKit.createContainer(clientKey, bean);
//            if (containerResponse.getWarnings().length > 0) {
//                throwError(containerResponse.getWarnings()[0]);
//            }
            return true;
        });
    }

    public boolean remove(String token, String serverId, String containerId, String containerName, String userId) {
        Okv cond = Okv.create()
                .set("c.server_id = ", serverId)
                .set("c.container_name = ", containerName)
                .set("c.status_flag = ", "1");
        Record container = containerDao.info(Okv.by("cond", cond));
        if (!StrKit.notNull(container)) {
            return DockerKit.removeContainer(getClientKey(token, serverId), containerId);
        }
        container.set("status_flag", "0");
        container.set("remark", "删除容器");
        container.set("update_time", getNowDateTime());
        container.set("update_oper_id", userId);
        return tx(() -> {
            if (!containerDao.update(container)) {
                throwError("容器删除失败");
            }
            return DockerKit.removeContainer(getClientKey(token, serverId), containerId);
        });
    }

    public Record cmd(String serverId, String containerName) {
        Okv cond = Okv.create()
                .set("c.server_id = ", serverId)
                .set("c.container_name = ", containerName)
                .set("c.status_flag = ", "1");
        Record container = containerDao.cmd(Okv.by("cond", cond));
        if (!StrKit.notNull(container)) {
            throwError("未找到创建信息");
        }
        return container;
    }

    public List<Record> look(Okv cond) {
        return containerDao.look(cond);
    }

    public Record detail(Okv cond) {
        return containerDao.detail(cond);
    }

    public void onMessage(WebsocketPool socketPool, JSONObject msgJson) {
        switch (msgJson.getString("cmd")) {
            case WebsocketCMD.ON_MESSAGE:
                ShellUtil.transToSSH(socketPool.getConnect_key(), msgJson.getJSONObject("data").getString("data"));
                break;
            default:
                //to do some thing
                break;
        }
    }

}
